#ifndef __LDX_CMESHCACHE_H_INCLUDE__
#define __LDX_CMESHCACHE_H_INCLUDE__
#include "LDXConfig.h"
#include "IMeshCache.h"

namespace ldx
{
	namespace scene
	{
		class CMeshCache :public IMeshCache
		{
		public:
			CMeshCache();

			//! Destructor
			virtual ~CMeshCache();

			//! Adds a mesh to the internal list of loaded meshes.
			/** Usually, CSceneManager::getMesh() is called to load a mesh
			from a file. That method searches the list of loaded meshes if
			a mesh has already been loaded and returns a pointer to if it
			is in that list and already in memory. Otherwise it loads the
			mesh. With IMeshCache::addMesh(), it is possible to pretend
			that a mesh already has been loaded. This method can be used
			for example by mesh loaders who need to load more than one mesh
			with one call. They can add additional meshes with this method
			to the scene manager. The COLLADA loader for example uses this
			method.
			\param name Name of the mesh. When calling
			CSceneManager::getMesh() with this name it will return the mesh
			set by this method.
			\param mesh Pointer to a mesh which will now be referenced by
			this name. */
			virtual void addMesh(const std::string& name, IAnimatedMesh* mesh);

			//! Removes the mesh from the cache.
			virtual void removeMesh(const IMesh* const mesh);

			//! Returns amount of loaded meshes in the cache.
			virtual mt::uint getMeshCount() const;

			//! Returns current index number of the mesh or -1 when not found.
			virtual int getMeshIndex(const IMesh* const mesh) const;

			//! Returns a mesh based on its index number.
			virtual IAnimatedMesh* getMeshByIndex(mt::uint index);

			//! Returns a mesh based on its name.
			virtual IAnimatedMesh* getMeshByName(const std::string& name);

			//! Get the name of a loaded mesh, based on its index.
			virtual const std::string& getMeshName(mt::uint index) const;

			//! Get the name of the loaded mesh if there is any.
			virtual const std::string& getMeshName(const IMesh* const mesh) const;

			//! Renames a loaded mesh.
			/** Note that renaming meshes might change the ordering of the
			meshes, and so the index of the meshes as returned by
			getMeshIndex() or taken by some methods will change.
			\param index The index of the mesh in the cache.
			\param name New name for the mesh.
			\return True if mesh was renamed. */
			virtual bool renameMesh(mt::uint index, const std::string& name);

			//! Renames the loaded mesh
			/** Note that renaming meshes might change the ordering of the
			meshes, and so the index of the meshes as returned by
			getMeshIndex() or taken by some methods will change.
			\param mesh Mesh to be renamed.
			\param name New name for the mesh.
			\return True if mesh was renamed. */
			virtual bool renameMesh(const IMesh* const mesh, const std::string& name);

			//! Check if a mesh was already loaded.
			virtual bool isMeshLoaded(const std::string& name);

			//! Clears the whole mesh cache, removing all meshes.
			virtual void clear();

			//! Clears all meshes that are held in the mesh cache but not used anywhere else.
			virtual void clearUnusedMeshes();

			private:
				struct MeshEntry
				{
					MeshEntry(const std::string& name)
						:NamedPath(name)
					{

					}
					std::string NamedPath;
					IAnimatedMesh* Mesh;

					bool operator<(const MeshEntry& other)const
					{
						return (NamedPath < other.NamedPath);
					}

					bool operator==(const std::string& name)
					{
						return NamedPath == name;
					}
				};

				std::vector<MeshEntry> Meshes;
				std::string EmptyMeshName;

		};
	}
}

#endif//! __LDX_CMESHCACHE_H_INCLUDE__